#!/bin/bash
#高级变量有三个主题:1.变量扩展 2.命令替换 3.算数扩展.基本形式如下:
#基本型			扩展种类		范例
#${变量名}		变量扩展		${var}
#$(命令)		命令替换		$(ls /)
#$((算数式))		算数扩展		$((9+9))


#变量扩展:测试存在性及空值
#存在即表示在使用前对该变量已申明,变量的值可能为空
#1.在变量值不存在时返回默认值,否则返回变量值
echo '变量存在与否的判断,语法:${变量名-默认值}'
var1=10
echo "var1:${var1-1}"
echo "var2:${var2-2}"
#2.在变量不存在或者值为空时返回默认值,否则返回变量值
echo '变量不存在或者值为空的判断,语法:${变量名:-默认值}'
var2=
echo "var1:${var1:-1}"
echo "var2:${var2:-2}"
echo "var3:${var3:-3}"
#3.在变量值为空或者不存在时给变量设置默认值,否则返回变量值
echo '变量值为空或者不存在时给变量设置默认值,语法:${变量名:=默认值}'
echo "var1:${var1:=1}"
echo "${var3:=3}"
echo "var3:$var3"
#4.在变量值为空或者不存在时提示错误信息,否则返回变量值
echo '变量值为空或者不存在时提示错误信息,语法:${变量名:?提示信息}'
echo "var3:${var3:?'变量var3不存在'}"
echo "var4:$var4"
#echo "var4:${var4:?'变量var4不存在'}"	#这句话会导致后面的脚本无法执行
#5.在变量存在时返回指定真值,否则返回null
echo '变量存在时返回指定真值,语法:${变量名+真值}'
echo "检查var3存在性的结果:${var3+'ture'}"
echo "检查var4存在性的结果:${var4+'ture'}"
: <<MINE
\${变量名+真值}的用途:
demo.sh
#!/bin/bash
exec grep -F ${1+"$@"}
这里使用exec执行grep程序,-F表示使用一串固定的字符串(可用换行字符分开)作为寻找的样式.
其中${1+"$@"}的意思是:若$1存在(即指定要寻找的关键字),则传回所有的参数$@,这表示一次可以搜寻多个文件
例如:./demo.sh Men /proc/meminfo /root/test.txt
MINE
#格式			描述
#${变量名-默认值}	变量不存在时返回默认值
#${变量名:-默认值}	变量不存在或者为空时返回默认值
#${变量名=默认值}	变量不存在,给变量赋予默认值
#${变量名:=默认值}	变量不存在或为空,给变量赋予默认值
#${变量名?提示信息}	变量不存在时显示错误信息
#${变量名:?提示信息}	变量不存在或为空时显示错误信息
#${变量名+真值}		变量存在时返回真值
#${变量名:+真值}	变量存在且非空时返回真值


#变量扩展:取字符串子串/字符串长度
#1.取字符串子串,字符串第一个字符编号为0.取子串的方式有两种:
echo '取子字符串方式一--语法:${变量:位置起点}'
#将由指定的位置开始,截取子字符串到字符串结束位置.
str1="linux shell"
substr=${str1:6}
echo "子字符串为:$substr"
echo '曲子字符串方式二--语法:${变量:位置起点:长度}'
#将由指定起始位置开始,截取指定长度的子字符串.
substr=${str1:0:5}
echo "子字符串为:$substr"
: <<MINE
\${变量:位置起点:长度}的用途
echo "-${IFS:0:1}-"
echo "-${IFS:1:2}-"
echo "-${IFS:2:3}-"
MINE
#2.计算字符串长度
echo '计算字符串长度,语法:${#变量名}'
echo "$str1的长度为:${#str1}"
echo "$substr的长度为:${#substr}"
: <<MINE
这种做法不行!
str2="this is a test"
echo "${str2:0:${#'this is'}}"
MINE
#格式			描述
#${变量名:起始位置}	截取由起始位置到串尾的子字符串
#${变量名:起始位置:长度}	截取由起始位置开始指定长度的子字符串


#对比样式:在字符创中查找符合规定样式的子串
#1.由字符串前段开始查找,删除相符项
filename="/usr/share/background"
echo "原串为:$filename"
echo '由字符串前段开始查找,删除最短匹配项.语法:${变量名#样式}'
echo ${filename#/*/}
echo '由字符串前段开始查找,删除最长匹配项.语法:${变量名##样式}'
echo ${filename##/*/}
echo '由字符串尾部开始查找,删除最短匹配项.语法:${变量名%样式}'
echo ${filename%/*}
echo '由字符串尾部开始查找,删除最长匹配项.语法:${变量名%%样式}'
echo ${filename%%a*}
#2.取代或者删除部分字符串
echo '只替换第一个符合项,并且取符合样式的最长子字符串.语法:${变量名/样式/替换字符串}'
echo "${filename/\//:}"
echo '替换所有符合样式的字符串.语法:${变量名//样式/替换字符串}'
echo "${filename//\//:}"
echo '删除符合样式的字符串,且只删除第一个符合项.语法:${变量名/样式/}'
echo "${filename/\//}"
echo '删除所有符合样式的字符串.语法:${变量名//样式/}'
echo "${filename//\//}"
echo '样式前加上#表示样式必须时在变量值的开头.语法:${变量名/#样式/}'
echo "${filename/#\/*\//}"
echo '样式前加上%表示样式必须时在变量值的结尾处.语法:${变量名/%样式/}'
echo "${filename/%\/*\//}"
#格式				描述
#${变量名#样式}			删除左边起第一个符合样式的字符串
#${变量名##样式}		删除左边起所有符合样式的字符串
#${变量名%样式}			删除右边起第一个符合样式的字符串
#${变量名%%样式}		删除右边起所有符合样式的字符串
#${变量名/样式/替换字符串}	将第一个符合样式的字符串替换为指定字符串
#${变量名//样式/替换字符串}	将所有符合样式的字符串替换为指定字符串
#${变量名/样式/}		删除变量中第一个符合样式的部分
#${变量名//样式/}		删除变量中所有符合样式的部分
#${变量名/#样式/}		将变量开头处符合样式的部分删除
#${变量名/%样式/}		将变量结尾处符合样式的部分删除


#变量扩展:取变量名称列表/数组索引列表
#1.取变量名称列表,列出所有变量名中以指定样式开头的变量名称.而且各变量之间使用$IFS定义的第一个分隔符隔开.
echo '取变量名称列表.语法:${!样式@}或者${!样式*}'
echo "以s开头的变量有:${!s@}"
echo "以v开头的变量有:${!v*}"
#2.获取数组的索引列表,每个索引值之间使用$IFS分隔.可以使用for循环遍历
echo '取数组的索引列表.语法:${!数组变量[@]}或者${!数组变量[*]}'
arr=(linux shell 1 2 3)
echo "arr数组为${arr[@]}"
echo "arr数组的索引为:${!arr[@]}"
echo "arr数组的索引为:${!arr[*]}"
#格式				描述
#${!样式@}			列出已指定样式开头的变量名
#${!样式*}			列出已指定样式开头的变量名
#${!数组名[@]}			列出数组的索引
#${!数组名[*]}			列出数组的索引


#命令替换:将命令执行后的标准输出放入变量中.命令替换的语法有两种:
#1.变量名=$(命令)
#2.变量名=`命令`
echo '命令替换:将命令执行后的标准输出放入变量中'
IFS_OLD=$IFS
IFS=' '
result=$(cat /etc/passwd| head -2)
echo $result
IFS=$IFS_OLD
: <<MINE
由于IFS改为空格符,所以在变量扩展时换行字符不会被删除.
这样保持了原文件的排版方式
如果要在命令替换中执行多个指令,需要用;将指令隔开
echo "$(cd ..; pwd)"
同时变量替换中也可以在包含其他命令替换.
MINE
echo "$(cd ..; pwd)"


#算数扩展:通过脚本执行算数运算
echo '算数扩展:通过脚本执行算数运算'
num=((8+2))
echo $num
